package com.burry.db;


import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import applelew.util.Debug;


public class SQLMachine {

	private SQLProcessor processor = null;

	private String helperName = null;
	private List colList = new ArrayList();
	/**
	 * 初始化
	 * @param helperName
	 * 重要说明1：
	 * SQLProcessor这个类，用new产生实例的时候，如果只传入helperName，那么
	 * 它自己会到连接池去取得连接，并且这个类会自己管理这个连接，包括提交和释放。
	 * 如果是传入helperName和一个连接来产生实例，则：这个连接的状态需要传入者
	 * 自己管理（包括提交和释放等）	
	 */
	public SQLMachine(String helperName) {
		/*
		 * 原来在这里新建processor的，现在改为每次实际查询的时候。这样子既不
		 * 用修改原来的代码，又保证了连接的安全释放。同时一个sqlMachine还可以多次
		 * 查询。同时也避免了新建sqlmachine的时候出错的情况调用者无法得知。
		 */
		this.helperName = helperName;
	}

	/**
	 * @param type
	 * @param value
	 * @return Object
	 */
	Object getValue(int type, String value) throws Exception {
		if (value == null) {
			return null;
		}
		switch (type) {
			case java.sql.Types.CHAR :
			case java.sql.Types.VARCHAR :
				return value;
			case java.sql.Types.DECIMAL :
			case java.sql.Types.NUMERIC :
			case java.sql.Types.REAL :
				return Double.valueOf(value);
			case java.sql.Types.DATE :
				return java.sql.Date.valueOf(value);
			case java.sql.Types.FLOAT :
				return Double.valueOf(value);
			case java.sql.Types.DOUBLE :
				return Double.valueOf(value);
			case java.sql.Types.INTEGER :
			case java.sql.Types.SMALLINT :
			case java.sql.Types.TINYINT :
				return Integer.valueOf(value);
			case java.sql.Types.LONGVARCHAR :
				return value;
			case java.sql.Types.TIME :
				return java.sql.Time.valueOf(value);
			case java.sql.Types.TIMESTAMP :
				return java.sql.Timestamp.valueOf(value);
		}
		
		return value;
	}

	/**
	 * @param result
	 * @param rs
	 */
	void loadResult(java.util.Map result, ResultSet rs) throws Exception {
		ResultSetMetaData rsmd = rs.getMetaData();
		int nColumnCount = rsmd.getColumnCount();
		if (!rs.next())
			return;
		for (int i = 1; i <= nColumnCount; i++) {
			result.put(
				rsmd.getColumnName(i),
				getValue(rsmd.getColumnType(i), rs.getString(i)));
			
		}
	}

	/**
	 * @param result
	 * @param rs
	 */
	void loadResult(java.util.List result, ResultSet rs) throws Exception {
		ResultSetMetaData rsmd = rs.getMetaData();
		int nColumnCount = rsmd.getColumnCount();
		while (rs.next()) {
			java.util.Map map = new HashMap();
			for (int i = 1; i <= nColumnCount; i++) {
				map.put(
					rsmd.getColumnName(i),
					getValue(rsmd.getColumnType(i), rs.getString(i)));
			}

			result.add(map); //add
		}
	}
	
	/**
	 * 更改一条记录 
	 * @param sql 需要执行的sql语句
	 * @return
	 * Map 
	 * 	key说明：
	 * 	msg:"SUCCESS" 成功 否则为相应的错误信息
	 * 	effectNum: Integer 影响的数据数目 如果发生任何错误该字段返回0,保证不会为空
	 */
	public java.util.Map updateResult(String sql) {
		java.util.Map result = new HashMap();
		try {
			processor = new SQLProcessor(this.helperName);

		    processor.prepareStatement(sql);
		    int i = processor.executeUpdate();
			//rs不用关闭,关闭processor的时候会自动关闭,但是要置为null,便于系统回收资源.
			//processor不用显示commit,因为close的时候会自动commit
		    result.put("msg","SUCCESS");
		    result.put("effectNum",new Integer(i));
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:sql[" +sql+"] error["+ ex.getMessage()+"]";
			Debug.logError(ex, msg);
			result.put("msg",msg);
			result.put("effectNum",new Integer(0));
			return result;
		} finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着
		}
		return result;
	}
	
	public List getColumnList(){
		return colList;
	}
	
	public java.util.List getResultSetWithCol(String sql) {
		java.util.List result = new ArrayList();
		try {
			processor = new SQLProcessor(this.helperName);
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}
		try {
			ResultSet rs = processor.executeQuery(sql);
			// build colList
			colList.clear();
			ResultSetMetaData rsmd = rs.getMetaData();
			for(int i=1;i<=rsmd.getColumnCount();i++){
				colList.add(rsmd.getColumnName(i));
			}
			
			//build end
			loadResult(result, rs);
			//rs不用关闭,关闭processor的时候会自动关闭,但是要置为null,便于系统回收资源.
			//processor不用显示commit,因为close的时候会自动commit
			rs = null;	
		} catch (Exception ex) {
			String msg = "getResultSet error:" + sql + "::" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着
		}
		return result;
	}
	
	/**
	 * 返回一条记录
	 * @param sql
	 * @return java.util.Map 返回null表明查询出错
	 */
	public java.util.Map getResult(String sql) {
		java.util.Map result = new HashMap();
		try {
			processor = new SQLProcessor(this.helperName);
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}
		try {
			ResultSet rs = processor.executeQuery(sql);
			loadResult(result, rs);
			//rs不用关闭,关闭processor的时候会自动关闭,但是要置为null,便于系统回收资源.
			//processor不用显示commit,因为close的时候会自动commit
			rs = null;
		} catch (Exception ex) {
			String msg = "getResult error:" + sql + "::" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		} finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着
		}
		return result;
	}

	/**
	 * 返回记录集合
	 * @param sql
	 * @return java.util.List 返回null表明查询出错。
	 */
	public java.util.List getResultSet(String sql) {
		java.util.List result = new ArrayList();
		try {
			processor = new SQLProcessor(this.helperName);
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}
		try {
			ResultSet rs = processor.executeQuery(sql);
			loadResult(result, rs);
			//rs不用关闭,关闭processor的时候会自动关闭,但是要置为null,便于系统回收资源.
			//processor不用显示commit,因为close的时候会自动commit
			rs = null;	
		} catch (Exception ex) {
			String msg = "getResultSet error:" + sql + "::" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着
		}
		return result;
	}
	
	/**
	 * 关闭资源.主要是关闭SQLProcessor.其他资源的关闭由processor.close();自动完成
	 * 包括commit
	 * 修改成为public 因为某些应用需要用到
	 * @return
	 */
	public boolean close(){
		try {
			processor.close();
			processor = null;
			return true;
		} catch (Exception e) {
			Debug.logError(e, "Error closing the SQLProcessor in SQLMachine");
			processor = null;
			return false;
		}
	}
	
	/*
	 * 应广大人群的需要特多此返回ResultSet的方法，谢谢
	 * <!-- 已废弃，因连接不好回收 -->
	 * @author yang.liu
	 * @return ResultSet
	 */
	
	public ResultSet getResutlSet(String sql)
	{
		ResultSet rs=null;
		try {
			processor = new SQLProcessor(this.helperName);
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}
		try {
			rs = processor.executeQuery(sql);
			
		} catch (Exception ex) {
			String msg = "getResultSet error:" + sql + "::" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着 ^_^ 用完了关
		}
		return rs;
	}
	
	public java.util.List getResultSetWithoutClose(String sql) {
		java.util.List result = new ArrayList();
		try {
			if(processor == null)
				processor = new SQLProcessor(this.helperName);
		} catch (Exception ex) {
			String msg = "SQLMachine new SQLProcessor ERROR:" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}
		try {
			ResultSet rs = processor.executeQuery(sql);
			loadResult(result, rs);
			//rs不用关闭,关闭processor的时候会自动关闭,但是要置为null,便于系统回收资源.
			//processor不用显示commit,因为close的时候会自动commit
			rs = null;	
		} catch (Exception ex) {
			String msg = "getResultSet error:" + sql + "::" + ex.getMessage();
			Debug.logError(ex, msg);
			return null;
		}finally{
			this.close();//关闭资源,一定要关闭资源,不然连接就占用着
		}
		return result;
	}
	
	public static void main(String[] args){
		SQLMachine sm = new SQLMachine("mine");
		List a = sm.getResultSet("select * from tbfund");
		System.out.println(a);
		
	}
}
